package com.fingard.dsp.bank.directbank.abc24;

import java.util.Date;

import com.fingard.constant.Format;
import com.fingard.dsp.bank.directbank.DirectBase;
import com.fingard.dsp.bank.directbank.abc24.util.DESUtil;
import com.fingard.net.ITcpClient;
import com.fingard.net.TcpPortClient;
import com.fingard.net.TcpReceiver;
import com.fingard.text.StringHelper;
import com.fingard.util.DateHelper;
import com.fingard.util.TransIDHelper;
import com.fingard.xml.XElement;
import com.fingard.xml.XmlTextReader;
import com.fingard.xml.XmlTextWriter;

import sun.misc.BASE64Encoder;

public class ABC24Base extends DirectBase implements ITcpClient {
	private static TransIDHelper idHelper = new TransIDHelper(1, 999);

    protected String getQryTransID() {
        Date tmpDateNow = new Date();
        return Format.DateTime12Year2Format.format(tmpDateNow) + idHelper.getNextIDStr();
    }
    
    protected String getCharset() {
		return getBankConfig().getCharset("GBK");
	}
	
	public void writeCommonHead(XmlTextWriter xmlWriter) throws Exception {
		xmlWriter.writeStartDocByDeclaration("<?xml version=\"1.0\" encoding=\"" + getCharset() + "\"?>");
	}
	
	/**
	 * 发送数据到银行
	 * 
	 * @param tmpReqData
	 * @return
	 * @throws Exception
	 */
	protected String[] sendToBank(String tmpReqData) throws Exception {
		String[] tmpStrRet = new String[] { "", "" };
		
		boolean needLogin = true;
		if(StringHelper.isNullOrEmpty(bankFront.token) || bankFront.customMap.containsKey("lastLoginTime")) {
			if (bankFront.customMap.containsKey("lastLoginTime")) {
	            String strLastTime = bankFront.customMap.get("lastLoginTime");
	            this.WriteBankLogLnNoTime("上次签到时间：" + strLastTime);
	            Date lastLoginTime = Format.DateTimeFormat.parse(strLastTime);
	            if (DateHelper.isSameDay(lastLoginTime, new Date())) {
	                needLogin = false;
	            }
	        } 
			if (needLogin) {
            	String[] tmpRetStr = exchangeKey();
            	if (tmpRetStr[0].length() > 0) {
            		tmpStrRet[0] = "-1";
            		tmpStrRet[1] = tmpRetStr[1];
            		return tmpStrRet;
            	}
            }
		}
		WriteBankLogLn2("通讯交互密钥内容:" + bankFront.token+"，字符集："+getCharset());
		tmpReqData = tmpReqData+"       ";//加7个空格，明文长度,不是8的倍数的,需要用空格补齐
		WriteBankLogLn2("加密前明文报文（加7个空格）:\r\n" + tmpReqData);
		byte[] bytesToEncrypt = tmpReqData.getBytes(getCharset());
		int remain = bytesToEncrypt.length % 8;
		int encryptLen = bytesToEncrypt.length - remain;
		byte[] tmpBytesBody = DESUtil.encryptionDes(bytesToEncrypt, bankFront.token.getBytes(getCharset()),encryptLen);
		BASE64Encoder encoder64 = new BASE64Encoder();
		String encryptMsg64 = encoder64.encode(tmpBytesBody);
		WriteBankLogLn2("加密后密文报文（base64）:\r\n" + encryptMsg64);
		
		//byte[] tmpBytesBody = tmpReqEncrptMsg.getBytes(getCharset());
		String tmpHead = String.format("%8s", tmpBytesBody.length);
		byte[] tmpBytesHead = tmpHead.getBytes(getCharset());

		byte[] tmpBytesSend = new byte[tmpBytesHead.length + tmpBytesBody.length];
		System.arraycopy(tmpBytesHead, 0, tmpBytesSend, 0, tmpBytesHead.length);
		System.arraycopy(tmpBytesBody, 0, tmpBytesSend, tmpBytesHead.length, tmpBytesBody.length);
		WriteBankLogStep2(tmpHead + tmpReqData);
		
		TcpPortClient tmpClient = new TcpPortClient(bankFront.serverIP, Integer.parseInt(bankFront.serverPort), this);
		WriteBankUrlLogLn(bankFront.serverIP + ":" + bankFront.serverPort);
		
		TcpReceiver tmpReceiver = tmpClient.sendMessage(tmpBytesSend);
        tmpStrRet[0] = tmpReceiver.connState;
        byte[] retCipherBytes = null;
        if (tmpReceiver.recBytes != null) {
        	int offSet = 0;
        	if(tmpReceiver.contentStartIndex>=0){
        		offSet = tmpReceiver.contentStartIndex;
        	}
        	if(tmpReceiver.readedLength - offSet > 0){
        		retCipherBytes = new byte[tmpReceiver.readedLength - offSet];
        		System.arraycopy(tmpReceiver.recBytes, offSet, retCipherBytes, 0, retCipherBytes.length);
        	}
            //tmpStrRet[1] = new String(tmpReceiver.recBytes, 0, tmpReceiver.readedLength, getCharset());
        }
        if (!tmpReceiver.isCompleted) {
            WriteBankLogLn(tmpReceiver.getConnMsg());
        }
        //WriteBankLogStep3(tmpStrRet[1]);
        //tmpStrRet[1] = tmpStrRet[1].substring(8);
        if(retCipherBytes != null){
        	WriteBankLogLn("解密前密文（base64）:" + encoder64.encode(retCipherBytes));
            WriteBankLogLn("解密前密钥:" + bankFront.token);
            byte[] plainBytes = DESUtil.decryptionDes(retCipherBytes, bankFront.token.getBytes(getCharset()));
            String plainTxt = new String(plainBytes,0,plainBytes.length,getCharset());
            WriteBankLogLn2("解密后明文报文:\r\n" + plainTxt);
            tmpStrRet[1] = plainTxt;
        }else{
        	tmpStrRet[1] = "接收字节为空，总接收字节数："+tmpReceiver.readedLength+"，contentStartIndex："+tmpReceiver.contentStartIndex;
        }

		return tmpStrRet;
	}
	
	public String[] exchangeKey() throws Exception {
		ABC24Header tmpBankHeader = new ABC24Header();
		tmpBankHeader.transCode = ABC24TransCode.getSecretKey;
		tmpBankHeader.reqSeqNo = getQryTransID();
		
		XmlTextWriter xmlWriter = new XmlTextWriter();
		writeCommonHead(xmlWriter);
		
		XElement tmpXElement = new XElement("ReqMsg", "");
		tmpXElement.addChild(new XElement("TxnType", tmpBankHeader.transCode));
		tmpXElement.addChild(new XElement("ReqSeqNo", tmpBankHeader.reqSeqNo));
		tmpXElement.addChild(new XElement("SpId", bankFront.corpNo));
		tmpXElement.addChild(new XElement("ReqDate", Format.Date8Format.format(new Date())));
		tmpXElement.addChild(new XElement("ReqTime", Format.Time6Format.format(new Date())));
		xmlWriter.writeXElement(tmpXElement);
		xmlWriter.writeEndDocument();
		
		String tmpReqHeader = String.format("%8s", xmlWriter.toXmlString().getBytes(getCharset()).length);
		String tmpReqMsg = tmpReqHeader + xmlWriter.toXmlString();
		WriteBankLogLn("密钥交换请求报文:\r\n" + tmpReqMsg);
		
		TcpPortClient tmpClient = new TcpPortClient(bankFront.serverIP, Integer.parseInt(bankFront.serverPort), this);
		WriteBankUrlLogLn(bankFront.serverIP + ":" + bankFront.serverPort);
		
		TcpReceiver tmpReceiver = tmpClient.sendMessage(tmpReqMsg.getBytes(getCharset()));
		String[] tmpStrRet = new String[] { "", "" };
        tmpStrRet[0] = tmpReceiver.connState;
        if (tmpReceiver.recBytes != null) {
            tmpStrRet[1] = new String(tmpReceiver.recBytes, 0, tmpReceiver.readedLength, getCharset());
        }
        WriteBankLogLn("密钥交换响应报文:\r\n" + tmpStrRet[1]);
        if (!tmpReceiver.isCompleted) {
            WriteBankLogLn(tmpReceiver.getConnMsg());
        }
        if (tmpStrRet[1].contains("<")) {
    		tmpStrRet[1] = tmpStrRet[1].substring(tmpStrRet[1].indexOf("<"));
    	}
        if (tmpStrRet[0].length() == 0) {
			StringBuilder tmpSbMsg = new StringBuilder();
			XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
			if (tmpBkReader != null) {
				String tmpRespCode = tmpBkReader.getFirstText("/ResMsg/respCode");
				if ("0000".equals(tmpRespCode)) {
					bankFront.token = tmpBkReader.getFirstText("/ResMsg/Key");
					WriteBankLogLn("密钥获取成功,内容为:" + bankFront.token);
					bankFront.customMap.put("lastLoginTime", Format.DateTimeFormat.format(new Date()));
		            WriteBankLogLnNoTime("lastLoginTime:" + Format.DateTimeFormat.format(new Date()));
				} else {
					tmpStrRet[0] = "-1";
					tmpStrRet[1] = tmpBkReader.getFirstText("/ResMsg/respText");
				}
			} else {
				tmpStrRet[0] = "-1";
				tmpStrRet[1] = tmpSbMsg.toString();
			}
		} else {
			tmpStrRet[0] = "-1";
		}
		return tmpStrRet;
	}

    public void getContentLength(TcpReceiver p_receiver) throws Exception {
        if (p_receiver.contentLength == -1) {
            if (p_receiver.readedLength >= 8) {
                p_receiver.contentLength = Integer.parseInt(new String(p_receiver.recBytes, 0, 8, getCharset()).trim());
                p_receiver.contentStartIndex = 8;
            }
        }
    }
}
